package org.fujene.memman;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Collections;
import java.util.SortedSet;
import java.util.TreeSet;
import org.fujene.communicate.deleter.DeleterPackage;
import org.fujene.constants.Constants;

public final class DeleteFilter{
	private SortedSet<DeleterPackage> deletedIDs;
	private int deleteKeyType;
	private int deleteKeyIndex;
	private File backupFile;
	private FileOutputStream backupStream;
	private DataOutputStream dataStream;

	public DeleteFilter(int deleteKeyType, int deleteKeyIndex){
		this.deletedIDs = Collections.synchronizedSortedSet(new TreeSet<DeleterPackage>());
		this.deleteKeyType = deleteKeyType;
		this.deleteKeyIndex = deleteKeyIndex;
		backupFile = new File(".deletefilter");
		if(backupFile.exists()){
			preprocess();
			backup();
		}
	}

	// Obtain lasted data when system stopped unsuccessfully
	private void backup(){
		FileInputStream inputStream = null;
		try{
			inputStream = new FileInputStream(backupFile);
			DataInputStream stream = new DataInputStream(inputStream);

			char length = stream.readChar();
			if(deleteKeyIndex == Constants.DELETE_TYPE_ID || deleteKeyIndex == Constants.DELETE_TYPE_TIME){
				deletedIDs.add(new DeleterPackage(stream.readLong()));
			}else if(deleteKeyIndex == Constants.DELETE_TYPE_MULTIFLAG){
				deletedIDs.add(new DeleterPackage(stream.readInt()));
			}else{
				byte[] b = new byte[length];
				stream.read(b);
				deletedIDs.add(new DeleterPackage(new String(b, Charset.forName("UTF-8"))));
			}
		}catch(FileNotFoundException e){}catch(IOException e){}finally{
			if(inputStream != null) try{
				inputStream.close();
			}catch(IOException e){}
		}
	}

	private void preprocess(){
		if(backupStream == null){
			try{
				backupStream = new FileOutputStream(backupFile);
				dataStream = new DataOutputStream(backupStream);
			}catch(FileNotFoundException e){}
		}
	}

	public void deleteFile(){
		backupFile.deleteOnExit();
	}

	public void add(String strval){
		preprocess();
		deletedIDs.add(new DeleterPackage(strval));
		byte[] b = strval.getBytes(Charset.forName("UTF-8"));
		try{
			dataStream.writeChar(b.length);
			dataStream.write(b);
		}catch(IOException e){}
	}

	public void add(long ID){
		preprocess();
		deletedIDs.add(new DeleterPackage(ID));
		try{
			dataStream.writeChar(8);
			dataStream.writeLong(ID);
		}catch(IOException e){}
	}

	public void add(int flagval){
		preprocess();
		deletedIDs.add(new DeleterPackage(flagval));
		try{
			dataStream.writeChar(4);
			dataStream.writeInt(flagval);
		}catch(IOException e){}
	}

	@Deprecated
	public void add(DeleterPackage pkg){
		preprocess();
		deletedIDs.add(pkg);
	}

	public void remove(String strval){
		deletedIDs.remove(new DeleterPackage(strval));
	}

	public void remove(long ID){
		deletedIDs.remove(new DeleterPackage(ID));
	}

	public void remove(int flagval){
		deletedIDs.remove(new DeleterPackage(flagval));
	}

	public boolean filter(String strval){
		return deletedIDs.contains(new DeleterPackage(strval));
	}

	public boolean filter(long ID){
		return deletedIDs.contains(new DeleterPackage(ID));
	}

	public boolean filter(int flagval){
		return deletedIDs.contains(new DeleterPackage(flagval));
	}

	public int deleteKeyIndex(){
		return deleteKeyIndex;
	}

	public int deleteKeyType(){
		return deleteKeyType;
	}

	@Override
	protected void finalize() throws Throwable{
		if(dataStream != null) dataStream.close();
		deleteFile();
		super.finalize();
	}
}
